package com.xbongbong.parent.abstracts;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.SubFormPoJo;
import com.xbongbong.paas.help.UserHelper;
import com.xbongbong.paas.model.ContractEditFileModel;
import com.xbongbong.paas.model.ContractTemplateBaseModel;
import com.xbongbong.paas.pojo.dto.AnalysisDataDTO;
import com.xbongbong.paas.pojo.dto.ParseSingleRowDataDTO;
import com.xbongbong.paas.pojo.vo.LinkResultDataVO;
import com.xbongbong.paas.pojo.vo.ParseSingleRowDataVO;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.formexplain.pojo.dto.HandlerExplainDTO;
import com.xbongbong.pro.onlineEditor.TemplateFieldValuePojo;
import com.xbongbong.saas.domain.entity.ContractEditFileEntity;
import com.xbongbong.saas.domain.entity.ContractTemplateBaseEntity;
import com.xbongbong.saas.domain.entity.DistributorAreaEntity;
import com.xbongbong.saas.model.DistributorAreaModel;
import com.xbongbong.sys.domain.entity.UserEntity;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * @author: wufeng
 * @date: 2018/12/11 15:18
 * @desrcption:
 */
@Component
public abstract class AbstractFormDataAnalysisDataHelp {

    private static final Logger LOG = LoggerFactory.getLogger(AbstractFormDataAnalysisDataHelp.class);

    @Resource
    private DistributorAreaModel distributorAreaModel;
    @Resource
    private ContractTemplateBaseModel contractTemplateBaseModel;
    @Resource
    private ContractEditFileModel contractEditFileModel;

    /**
     * 解析单行数据（表单数据详情和编辑回显都获取了此接口）
     * @param parseSingleRowDataDTO
     * @throws XbbException
     * @return LinkResultDataVO 关联数据和关联查询相关
     */
    public ParseSingleRowDataVO parseSingleRowData(ParseSingleRowDataDTO parseSingleRowDataDTO) throws XbbException{
        ParseSingleRowDataVO parseSingleRowDataVO = new ParseSingleRowDataVO();
        LinkResultDataVO linkResultDataVO = new LinkResultDataVO();
        Set<Object> linkDataSet = new HashSet<>();
        JSONObject dataJsonObject = parseSingleRowDataDTO.getDataJsonObject();
        JSONObject resultObject = (JSONObject) dataJsonObject.clone();
        try {
            Map<String, FieldAttrEntity> explainMap = parseSingleRowDataDTO.getExplainMap();
            Map<String, Object> linkData = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            Iterator iterator = dataJsonObject.keySet().iterator();
            AnalysisDataDTO analysisDataDTO = new AnalysisDataDTO();
            BeanUtil.copyProperties(parseSingleRowDataDTO, analysisDataDTO);
            HandlerExplainDTO handlerExplainDTO = new HandlerExplainDTO();
            BeanUtil.copyProperties(parseSingleRowDataDTO, handlerExplainDTO);
            while (iterator.hasNext()) {
                String key = Objects.toString(iterator.next());
                FieldAttrEntity fieldAttrEntity = explainMap.get(key);
                if(fieldAttrEntity == null) {
                    analysisNotExistField(key, dataJsonObject, resultObject, parseSingleRowDataDTO.getUserMap(), parseSingleRowDataDTO.getSaasMark());
                    continue;
                }
                // 子表单的解析
                if(Objects.equals(fieldAttrEntity.getFieldType(), FieldTypeEnum.SUB_FORM.getType())
                        || Objects.equals(fieldAttrEntity.getFieldType(), FieldTypeEnum.CONTACT_NUMBER.getType())
                        || Objects.equals(fieldAttrEntity.getFieldType(), FieldTypeEnum.SINGLE_SUB_FORM.getType())
                        || Objects.equals(fieldAttrEntity.getFieldType(), FieldTypeEnum.SWITCH_TEXT.getType())
                        || Objects.equals(fieldAttrEntity.getFieldType(), FieldTypeEnum.SELECT_SERVICE.getType())
                        || Objects.equals(fieldAttrEntity.getFieldType(), FieldTypeEnum.SELECT_PRODUCT.getType())){
                    try {
                        JSONArray jsonArray = dataJsonObject.getJSONArray(key) == null ? new JSONArray() : dataJsonObject.getJSONArray(key);
                        JSONArray resultJsonArray = new JSONArray();
                        List<Map<String, Object>> subLinkDataList = new ArrayList<>();
                        SubFormPoJo subForm = fieldAttrEntity.getSubForm();
                        List<? extends FieldAttrEntity> items = (subForm == null || subForm.getItems() == null) ? new ArrayList<>() : subForm.getItems();
                        Map<String, FieldAttrEntity> subExplainMap = ExplainUtil.getExplainMapByList(items);
                        // 判断高级规则
                        boolean invisibleOfScope = ExplainUtil.invisibleOfScope(fieldAttrEntity, handlerExplainDTO);
                        if (invisibleOfScope && (Objects.isNull(parseSingleRowDataDTO.getIsProcess()) || !parseSingleRowDataDTO.getIsProcess())) {
                            // 子表单字段高级规则，列表隐藏数据
                            if (Objects.equals(1, parseSingleRowDataDTO.getListFlag())) {
                                resultObject.put(key, resultJsonArray);
                            }
                            continue;
                        }
                        // 公海池是否可见
                        boolean publicVisible = publicIsVisible(dataJsonObject, fieldAttrEntity);
                        if (publicVisible) {
                            // 公海池不可见
                            resultObject.put(key, new JSONArray());
                            continue;
                        }
                        for (int i = 0; i < jsonArray.size(); i++) {
                            if (!(jsonArray.get(i) instanceof Map)) {
                                continue;
                            }
                            JSONObject subJsonObject = jsonArray.getJSONObject(i);
                            Iterator subIterator = subJsonObject.keySet().iterator();
                            JSONObject subResult = new JSONObject();
                            Map<String, Object> subLinkData = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                            while (subIterator.hasNext()) {
                                String subKey = Objects.toString(subIterator.next());
                                FieldAttrEntity subFieldAttrEntity = subExplainMap.get(subKey);
                                if (subFieldAttrEntity == null) {
                                    subResult.put(subKey, subJsonObject.get(subKey));
                                    continue;
                                }
                                analysisDataDTO.setAttr(subKey);
                                analysisDataDTO.setFieldAttrEntity(subFieldAttrEntity);
                                analysisDataDTO.setDataJsonObject(subJsonObject);
                                analysisData(analysisDataDTO, subResult, subLinkData, linkDataSet);
                            }
                            if (!subLinkData.isEmpty()) {
                                subLinkDataList.add(subLinkData);
                            }
                            resultJsonArray.add(subResult);
                        }
                        linkData.put(key, subLinkDataList);
                        resultObject.put(key, resultJsonArray);
                    } catch (Exception e) {
                        LOG.warn("formDataListAnalysisDataHelp.parseSingleRowData表单单行数据解析-子表单的解析出错，dataId="+parseSingleRowDataDTO.getDataId()
                                + "--businessType=" + parseSingleRowDataDTO.getBusinessType(), e);
                    }
                } else {
                    try {
                        analysisDataDTO.setAttr(key);
                        analysisDataDTO.setFieldAttrEntity(fieldAttrEntity);
                        analysisDataDTO.setDataJsonObject(dataJsonObject);
                        analysisDataDTO.setFormId(parseSingleRowDataDTO.getFormId());
                        analysisData(analysisDataDTO, resultObject, linkData, linkDataSet);
                    } catch (Exception e) {
                        LOG.warn("formDataListAnalysisDataHelp.parseSingleRowData表单单行数据解析-常规，dataId="+parseSingleRowDataDTO.getDataId()
                                + "--businessType=" + parseSingleRowDataDTO.getBusinessType(), e);
                    }
                }
            }
            linkResultDataVO.setLinkDataSet(linkDataSet); // 本质上是个id列表
            linkResultDataVO.setLinkData(linkData); // key是关联数据的attr，value的话关联数据单选是id，关联数据多选是id数组
            parseSingleRowDataVO.setResult(resultObject);
            parseSingleRowDataVO.setLinkResultDataVO(linkResultDataVO);
        }catch (Exception e) {
            LOG.error("formDataListAnalysisDataHelp.parseSingleRowData表单单行数据解析出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return parseSingleRowDataVO;
    }

    /**
     * 解析特殊数据，地址，附件，定位，多选转成逗号隔开的字符串
     * @param analysisDataDTO 封装不变对象
     * @param linkDataSet 关联数据id容器
     * @param linkData 关联数据容器
     * @param resultJsonObject 数据结果容器
     * @see com.xbongbong.paas.enums.PlatFormEnum
     * @throws XbbException
     */
    public abstract void analysisData(AnalysisDataDTO analysisDataDTO, JSONObject resultJsonObject,
                                                   Map<String, Object> linkData, Set<Object> linkDataSet) throws XbbException;

    /**
     * 所在地区解析
     * @param analysisDataDTO
     * @param resultJsonObject
     * @param key
     * @param objectJsonObject
     */
    protected void analysisArea(AnalysisDataDTO analysisDataDTO, JSONObject resultJsonObject, String key, JSONObject objectJsonObject) {
        Long areaId = objectJsonObject.getLong(key);
        if (Objects.nonNull(areaId)) {
            DistributorAreaEntity distributorAreaEntity = distributorAreaModel.getByKey(areaId, analysisDataDTO.getCorpid());
            if (Objects.isNull(distributorAreaEntity)) {
                resultJsonObject.remove(key);
                return;
            }
            Map<String, String> resultMap = new HashMap<>(2);
            resultMap.put("id", Objects.toString(areaId));
            resultMap.put("name", distributorAreaEntity.getName());
            resultJsonObject.put(key, resultMap);
        }
    }


    /**
     * 解析下不存在字段的数据 目前只有ownerId字段
     * @param attr
     * @param data 未解析的元数据
     * @param resultData 解析后的数据
     * @param userMap
     */
    protected void analysisNotExistField(String attr, JSONObject data, JSONObject resultData, Map<String, UserEntity> userMap, Integer saasMark) {
        if (Objects.equals(SaasMarkEnum.PAAS.getCode(), saasMark) &&
                (Objects.equals(FieldTypeEnum.OWNERID.getAlias(), attr)
                || Objects.equals(FieldTypeEnum.COUSERID.getAlias(), attr))) {
            List<UserEntity> userList = UserHelper.getUserByKey(attr, resultData, userMap);
            List<String> nameList = new ArrayList<>();
            userList.forEach(item->{
                nameList.add(item.getName());
            });
            resultData.put(attr, StringUtils.join(nameList, "、"));
        }
    }
    /**
     * 公海池是否可见
     * @param data
     * @param fieldAttrEntity
     * @return boolean true 不可见， false：可见
     * @author 吴峰
     * @date 2022/9/22 10:04
     * @throws XbbException
     */
    protected boolean publicIsVisible(JSONObject data, FieldAttrEntity fieldAttrEntity) throws XbbException {
        return false;
    }
}
